
#include "variable/nvariableserver.h"
#include "scene/nrendercontext.h"
#include "scene/nsceneserver.h"
#include "kernel/ntimeserver.h"
#include "scene/nanimator.h"
#include "resource/nresourceserver.h"

#include "nanachronox/nmd2shapenode.h"

nNebulaScriptClass(nMD2ShapeNode, "nmaterialnode");

//------------------------------------------------------------------------------
/**
*/
nMD2ShapeNode::nMD2ShapeNode() :
    groupIndex(0)
{
    // obtain variable handles
    this->timeHandle = nVariableServer::Instance()->GetVariableHandleByName("time");
    this->windHandle = nVariableServer::Instance()->GetVariableHandleByName("wind");
}

//------------------------------------------------------------------------------
/**
*/
nMD2ShapeNode::~nMD2ShapeNode()
{
    // empty
}

//------------------------------------------------------------------------------
/**
    Load the resources needed by this object.
*/
bool
nMD2ShapeNode::LoadResources()
{
	if (this->LoadModel()) {
		if (nMaterialNode::LoadResources()) {
			return true;
		}
    }

	return false;
}

//------------------------------------------------------------------------------
/**
    Unload the resources if refcount has reached zero.
*/
void
nMD2ShapeNode::UnloadResources()
{
	this->UnloadModel();
    nMaterialNode::UnloadResources();
}

//------------------------------------------------------------------------------
bool
nMD2ShapeNode::LoadModel()
{
    nResourceServer* resServer = nResourceServer::Instance();
    this->model = (nMD2Model*) resServer->NewResource("nmd2model", "models:bootsdroid.md2", nResource::Other);
	if (model) {
		model->SetFilename("models:bootsdroid.md2");
		model->Load();
		return true;
	}
	return false;
}

//------------------------------------------------------------------------------
void
nMD2ShapeNode::UnloadModel()
{
	this->model->Release();
	this->model = 0;
}

//------------------------------------------------------------------------------
/**
    Compute the resulting modelview matrix and set it in the scene
    server as current modelview matrix.
*/
bool
nMD2ShapeNode::RenderTransform(nSceneServer* sceneServer,
                                    nRenderContext* renderContext,
                                    const matrix44& parentMatrix)
{
    n_assert(sceneServer);
    n_assert(renderContext);
    this->InvokeAnimators(nAnimator::Transform, renderContext);

    sceneServer->SetModelTransform(matrix44());
    return true;
}

//------------------------------------------------------------------------------
/**
*/
void
nMD2ShapeNode::RenderContextCreated(nRenderContext* renderContext)
{
    nMaterialNode::RenderContextCreated(renderContext);

    // see if resources need to be reloaded
    if (!this->AreResourcesValid())
    {
        this->LoadResources();
    }
}

//------------------------------------------------------------------------------
/**
    Indicate to scene server that we provide geometry
*/
bool
nMD2ShapeNode::HasGeometry() const
{
    return true;
}

//------------------------------------------------------------------------------
/**
    Perform pre-instance-rendering of particle system.
    FIXME: check if this is the optimal setup for the new instance 
    rendering!
*/
bool
nMD2ShapeNode::ApplyGeometry(nSceneServer* sceneServer)
{
    return true;
}

//------------------------------------------------------------------------------
/**
    - 15-Jan-04     floh    AreResourcesValid()/LoadResource() moved to scene server
*/
bool
nMD2ShapeNode::RenderGeometry(nSceneServer* sceneServer, nRenderContext* renderContext)
{
    n_assert(sceneServer);
    n_assert(renderContext);

    nVariable* timeVar = renderContext->GetVariable(this->timeHandle);
    n_assert2(timeVar, "No 'time' variable provided by application!");
    float curTime = timeVar->GetFloat();
    n_assert(curTime >= 0.0f);

    if (!this->dynMesh.IsValid())
    {
        this->dynMesh.Initialize(nGfxServer2::PrimitiveType::TriangleList,
			nMesh2::Coord  | nMesh2::Normal | nMesh2::Uv0, nMesh2::WriteOnly | nMesh2::NeedsVertexShader, false, false);
        n_assert(this->dynMesh.IsValid());
    }
	this->model->PopulateMesh(&dynMesh, this->groupIndex);

    return true;
}


// #include "resource/nresourceserver.h"
// #include "nanachronox/nmd2model.h"

//	nRef<nResourceServer> refResourceServer = (nResourceServer*) kernelServer.New("nresourceserver", "/sys/servers/resource");

//    nMD2Model* model = (nMD2Model*) refResourceServer->NewResource("nmd2model", "models:bootsdroid.md2", nResource::Other);
//	if (model) {
//		model->SetFilename("models:bootsdroid.md2");
//		model->Load();
//	}

//	if (model) {
//		model->Release();
//	}
